package com.apexsoft.assets.base.param;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.UUID;

public class TempFile extends InputStream {

    /** Field  */
    private static final Logger log = LoggerFactory.getLogger(TempFile.class);

    /** Field  临时文件流状态，支持读写切换*/
    private int state = 0;    // 1:读状态，2:写状态，0：未初始化状态

    /** Field  临时文件*/
    private File tempFile;

    /** Field  输出流*/
    private OutputStream fos;

    /** Field  输入流*/
    private InputStream fis;

    /** Field  文件名*/
    private String fileName;

    /**
     * Constructs
     *
     */
    public TempFile() {
        File folder = new File("temp");

        if (!folder.exists()) {
            if (!folder.mkdirs()) {
                throw new RuntimeException("临时文件空间创建失败，可能磁盘容量不足");
            }
        }

        tempFile = new File("temp" + File.separator + UUID.randomUUID().toString());

        if (!tempFile.exists()) {
            try {
                if (!tempFile.createNewFile()) {
                    throw new RuntimeException("临时文件创建失败，可能磁盘容量不足");
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public int available() throws IOException {
        return fis.available();
    }

    /**
     * Method 状态检查</p>
     *
     * 只有读状态，才可以做read操作</p>
     * 只有写状态，才可以做write操作</p>
     *
     *
     * @param targetState
     */
    private void checkState(int targetState) {
        if (targetState != state) {
            if (state == 0) {
                throw new RuntimeException(
                        "TempFile must call toWriteState or toReadState before write or read action");
            } else if (state == 1) {
                throw new RuntimeException("TempFile must call toWriteState first before wirte");
            } else if (state == 2) {
                throw new RuntimeException("TempFile must call toReadState first before read");
            }
        }
    }

    @Override
    public void close() throws IOException {
        toUnInstallState();
        tempFile.delete();
    }

    @Override
    public synchronized void mark(int readlimit) {
        fis.mark(readlimit);
    }

    @Override
    public boolean markSupported() {
        return fis.markSupported();
    }

    @Override
    public int read() throws IOException {
        checkState(2);

        return fis.read();
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        checkState(1);

        return fis.read(b, off, len);
    }

    @Override
    public synchronized void reset() throws IOException {
        fis.reset();
    }

    @Override
    public long skip(long n) throws IOException {
        return fis.skip(n);
    }

    /**
     * Method 切换到读状态
     *
     */
    public void toReadState() {
        if (fis == null) {
            try {
                fis = new FileInputStream(tempFile);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }

        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            fos = null;
        }

        state = 1;
    }

    /**
     * Method 切换的原始状态，不可读写
     *
     */
    public void toUnInstallState() {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            fos = null;
        }

        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            fis = null;
        }

        state = 0;
    }

    /**
     * Method 切换到写状态
     *
     */
    public void toWriteState() {
        if (fos == null) {
            try {
                fos = new FileOutputStream(tempFile);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }

        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            fis = null;
        }

        state = 2;
    }

    /**
     * Method 写流
     *
     *
     * @param bytes
     * @param length
     *
     * @throws IOException
     */
    public void write(byte[] bytes, int length) throws IOException {
        checkState(2);

        if (fos == null) {
            fos = new FileOutputStream(tempFile);
        }

        fos.write(bytes, 0, length);
    }

    public String getFileName() {
        return fileName;
    }

    public TempFile setFileName(String fileName) {
        this.fileName = fileName;
        return this;
    }
}

